#include<iostream>
#include<unistd.h>
#include<ctime>
#include<cstring>
#include<vector>
#include<unordered_map>
#include<sys/wait.h>
#include<sys/types.h>
#include<string>
#include<cassert> 
using std::cout;
using std::endl;
using std::cerr;
using std::vector;
using std::string;
using std::unordered_map;

typedef void(*function)();
vector<function> functions;
unordered_map<uint32_t,string> info;
void f1(){
    cout<<"This is a dairy task!,process pid::["<<getpid()<<"]"<<"time: ["<<time(nullptr)<<"]\n"<<endl;
}
void f2(){
    cout<<"This is a data task!,process pid::["<<getpid()<<"]"<<"time: ["<<time(nullptr)<<"]\n"<<endl;
}
void f3(){
    cout<<"This is a internet task!,process pid::["<<getpid()<<"]"<<"time: ["<<time(nullptr)<<"]\n"<<endl;
}

void loadFunc(){
    info.insert({functions.size(),"Deal dairy"});
    functions.push_back(f1);

    info.insert({functions.size(),"Deal data"});
    functions.push_back(f2);

    info.insert({functions.size(),"Deal Internet"});
    functions.push_back(f3);
}
int main(){
    loadFunc();
    int pipefd[2];
    int ret=pipe(pipefd);
    if(ret!=0){
        cerr<<"pipe error!"<<endl;
        return 1;
    }
    pid_t id = fork();
    if(id<0){
        cerr<<"fork error!"<<endl;
        return 2;
    }
    else if(id==0){
        close(pipefd[1]);
        while(true){
        uint32_t operatorType=0;
        ssize_t ret=read(pipefd[0],&operatorType,sizeof(uint32_t));
        if(ret==0){
            cout<<"Parent process has finished task distribution!\n"<<endl;
            break;
        }
        assert(ret=sizeof(uint32_t));
        (void)ret;
        if(operatorType <functions.size()){
            functions[operatorType]();
        }
        else{
            cout<<"BUG,operatorType::"<<operatorType<<endl;
        }
    }
        close(pipefd[1]);
        exit(0);
    }
    else{
        srand((long long)time(nullptr));
        close(pipefd[0]);
        int num=functions.size();
        int cnt=1;
        while(cnt<=10){
            uint32_t commandCode=rand()%num;
            cout<<"Parent process has distributed::"<<info[commandCode]<<"Time ::"<<cnt<<endl;
            cnt++;
            write(pipefd[1],&commandCode,sizeof(uint32_t));
            sleep(1);
        }
        close(pipefd[1]);
        pid_t result=waitpid(id,nullptr,0);
        if(result){
            cout<<"Wating success!"<<endl;
        }
    }
    return 0;
}
